package com.twu.biblioteca;

import java.util.ArrayList;
import java.util.HashMap;

public class BibliotecaApp {
    private Biblioteca biblioteca;

    public BibliotecaApp(Biblioteca biblioteca) {
        this.biblioteca = biblioteca;
    }

    public static void main(String[] args) {
        BibliotecaApp bibliotecaApp = new BibliotecaApp(new Biblioteca());

        bibliotecaApp.createDummyData();
        bibliotecaApp.run();
    }

    private void createDummyData() {
        biblioteca.createDummyData();
    }

    private void run() {
        int userInput;
        int optionToQuit;
        boolean userLoggedIn;

        printWelcomeMessage();

        userLoggedIn = attemptUserLogIn();

        optionToQuit = biblioteca.getMenu(userLoggedIn).size();

        do {
            printMenu(userLoggedIn);
            userInput = requestUserInput(biblioteca.MENU_SELECTION_PROMPT);
            processUserInput(userInput, userLoggedIn);
        } while (userInput != optionToQuit);
    }

    public void printWelcomeMessage() {
        System.out.print(biblioteca.getWelcomeMessage());
    }

    public boolean attemptUserLogIn() {
        String username;
        String password;
        username = biblioteca.requestUserInput(biblioteca.REQUEST_USERNAME_PROMPT);
        final String SKIP_LOGIN = "no";

        if (username.equalsIgnoreCase(SKIP_LOGIN)) {
            return false;
        }

        password = biblioteca.requestUserInput(biblioteca.REQUEST_PASSWORD_PROMPT);

        if (biblioteca.verifyUserLoginDetails(username, password)) {
            biblioteca.setCurrentUser(username);
            return true;
        }

        return false;

    }

    public void printMenu(boolean userLoggedIn) {
        HashMap<Integer,String> menu = biblioteca.getMenu(userLoggedIn);

        for (int menuId : menu.keySet()) {
            System.out.println("[" + menuId + "] " + menu.get(menuId));
        }
    }

    public int requestUserInput(String message) {
        int userInput = 0;
        try {
            userInput = Integer.parseInt(biblioteca.requestUserInput(message));
        } catch (NumberFormatException e) {
            System.out.println("\nYou did not make a valid selection. Please try again.");
        }

        return userInput;
    }

    public void processUserInput(int userInput, boolean userLoggedIn) {
        String defaultMessage = "Select a valid option!";

        if (userLoggedIn) {
            switch (userInput) {
                case 1: displayAllBooks();
                    break;
                case 2: displayAllMovies();
                    break;
                case 3: reserveBook(requestUserInput(biblioteca.BOOK_ID_PROMPT));
                    break;
                case 4: checkMembership();
                    break;
                case 5: break;
                default:
                    System.out.println(defaultMessage);
            }
        } else {
            switch (userInput) {
                case 1: displayAllBooks();
                    break;
                case 2: displayAllMovies();
                    break;
                case 3: checkMembership();
                    break;
                case 4: break;
                default:
                    System.out.println(defaultMessage);
            }
        }
    }

    public void displayAllBooks() {
        String headerFormat = "%1$4S %2$-30S %3$-20S %4$-10S%n";
        String recordFormat = "%1$4s %2$-30s %3$-20s %4$-10s%n";

        printSectionHeader(biblioteca.getDisplayAllBooksSectionHeader());
        printRecordHeadings(biblioteca.getBookListRecordHeadings(headerFormat));
        printBookListRecords(biblioteca.getBookList(), recordFormat);
    }

    public void displayAllMovies() {
        String headerFormat = "%1$-30S %2$5S %3$-20S %4$4S%n";
        String recordFormat = "%1$-30s %2$5s %3$-20s %4$4s%n";

        printSectionHeader(biblioteca.getDisplayAllMoviesSectionHeader());
        printRecordHeadings(biblioteca.getMovieListRecordHeadings(headerFormat));
        printMovieListRecords(biblioteca.getMovieList(), recordFormat);
    }

    public void printSectionHeader(String sectionHeader) {
        System.out.println(sectionHeader);
        System.out.println();
    }

    public void printRecordHeadings(String recordHeadings) {
        System.out.print(recordHeadings);
    }

    public void printBookListRecords(ArrayList<Book> bookList, String format) {
        for (Book aBook : bookList) {
            // displaying true/false can be confusing. A simple yes/no for whether
            // a book is available is better.
            String isAvailable = "Yes";
            if (aBook.isReserved()) isAvailable = "No";

            System.out.printf(
                    format,
                    aBook.getId(),
                    aBook.getTitle(),
                    aBook.getAuthor(),
                    isAvailable
            );
        }

        System.out.println();
    }

    public void printMovieListRecords(ArrayList<Movie> movieList, String format) {
        for (Movie aMovie : movieList) {
            // displaying a rating of 0 can be confusing. Rating 0 means it has no rating and should therefore
            // display as "N/A"
            String rating = "N/A";
            if (aMovie.getRating() != 0) rating = Integer.toString(aMovie.getRating());

            System.out.printf(
                    format,
                    aMovie.getTitle(),
                    aMovie.getYear(),
                    aMovie.getDirector(),
                    rating
            );
        }

        System.out.println();
    }

    public void reserveBook(int userInput) {
            if (biblioteca.reserveBook(userInput)) {
                System.out.println("Thank You! Enjoy the book!");
            } else {
                System.out.println("Sorry we don't have that book yet.");
            }
    }

    public void checkMembership() {
        String format = "%1$-20S %2$-20s%n";

        User user = biblioteca.getCurrentUser();

        if (user != null) {
            System.out.println();
            System.out.print(String.format(format, "Library ID: ", user.getUsername()));
            System.out.print(String.format(format, "Name: ", user.getName()));
            System.out.print(String.format(format, "Email: ", user.getEmail()));
            System.out.print(String.format(format, "Phone: ", user.getPhone()));
            System.out.println();
        } else {
            System.out.println();
            System.out.println("Please talk to a Librarian. Thank you.");
            System.out.println();
        }
    }
}
